
#include "sniffer.h"
rawsocket::rawsocket(const int protocol)
{
    sockfd=socket(PF_PACKET,SOCK_RAW,protocol);
    if(sockfd<0)
    {
	    perror("socket error: ");
    }
}

bool rawsocket::dopromisc(char*nif)
{
    struct ifreq ifr;              
    strncpy(ifr.ifr_name, nif,strlen(nif)+1);  
    if((ioctl(sockfd, SIOCGIFFLAGS, &ifr) == -1))  
    {         
       	perror("ioctlread: ");  
	    return false;
    }	
    ifr.ifr_flags |= IFF_PROMISC; 
    if(ioctl(sockfd, SIOCSIFFLAGS, &ifr) == -1 )
    { 
     	perror("ioctlset: ");
	    return false;
    }
    return true;
}

int rawsocket::receive(char *recvbuf,int buflen, struct sockaddr_in *from,int *addrlen)
{
    int recvlen;
    recvlen=recvfrom(sockfd,recvbuf,buflen,0,(struct sockaddr *)from,(socklen_t *)addrlen);
    recvbuf[recvlen]='\0';
    return recvlen;
}





void rawsocsniffer::setfilter(filter myfilter)
{
    simfilter.protocol=myfilter.protocol;
    simfilter.sip=myfilter.sip;
    simfilter.dip=myfilter.dip;
}

bool rawsocsniffer::testbit(const unsigned int p,int k)
{
    if((p>>(k-1))&0x0001)
	    return true;
    else
	    return false;
}

void rawsocsniffer::setbit(unsigned int &p,int k)
{
    p=(p)|((0x0001)<<(k-1));
}

void rawsocsniffer::sniffer()
{
    struct sockaddr_in from;
    int sockaddr_len=sizeof(struct sockaddr_in);
    int recvlen=0;
    while(1)
    {
    	recvlen=receive(packet,max_packet_len,&from,&sockaddr_len);
    	if(recvlen>0)
    	{
	        analyze();
    	}
   	    else
    	{
            perror("error?:");
	        continue;
    	}
    }	 
}

void rawsocsniffer::analyze()
{
    ether_header_t *etherpacket=(ether_header_t *)packet;
    if(simfilter.protocol==0)
	simfilter.protocol=0xff;
    switch (ntohs(etherpacket->frametype))
    {
	case 0x0800:
	    if(((simfilter.protocol)>>1))
	    {
	    	cout<<"\n\n/*---------------ip packet--------------------*/"<<endl;
	    	ParseIPPacket();
	    }
	    break;
	case 0x0806:
	    if(testbit(simfilter.protocol,1))
	    {
	    	cout<<"\n\n/*--------------arp packet--------------------*/"<<endl;
	    	ParseARPPacket();
	    }
	    break;
	case 0x0835:
	    if(testbit(simfilter.protocol,5))
	    {
		    cout<<"\n\n/*--------------RARP packet--------------------*/"<<endl;
		    ParseRARPPacket();
	    }
	    break;
	default:
	    cout<<"\n\n/*--------------Unknown packet----------------*/"<<endl;
	    cout<<"Unknown ethernet frametype!"<<endl;
	    break;
    }
}


void rawsocsniffer::ParseIPPacket()
{
    ip_packet_t *ippacket=(ip_packet_t *)packet; 
    cout<<"ipheader.protocol: "<<int(ippacket->ipheader.protocol)<<endl;
    if(simfilter.sip!=0)
    {
	    if(simfilter.sip!=(ippacket->ipheader.src_ip))
	    return;
    }
    if(simfilter.dip!=0)
        {
	    if(simfilter.dip!=(ippacket->ipheader.des_ip))
	    return;
    }
    switch (int(ippacket->ipheader.protocol))
    {
	case 1:
	    if(testbit(simfilter.protocol,4))
	    {
	    	cout<<"Received an ICMP packet"<<endl;
	    	ParseICMPPacket();
	    }
	    break;
	case 6:
	    if(testbit(simfilter.protocol,2))
	    {
	    	cout<<"Received an TCP packet"<<endl;
	    	ParseTCPPacket();
	    }
	    break;
	case 17:
	    if(testbit(simfilter.protocol,3))
	    {
	    	cout<<"Received an UDP packet"<<endl;
	    	ParseUDPPacket();
	    }
	    break;
/*省略针对其他协议的分析*/
    }
}

void rawsocsniffer::ParseTCPPacket()
{
    tcp_packet_t *tcppacket=(tcp_packet_t *)packet;
    cout<<setw(20)<<"MAC address: from ";
    print_hw_addr(tcppacket->etherheader.src_hw_addr);
    cout<<"to ";
    print_hw_addr(tcppacket->etherheader.des_hw_addr);
    cout<<endl<<setw(20)<<"IP address: from ";
    print_ip_addr(tcppacket->ipheader.src_ip);
    cout<<"to ";
    print_ip_addr(tcppacket->ipheader.des_ip);
    cout<<endl;
    cout<<setw(10)<<"srcport: "<<ntohs(tcppacket->tcpheader.src_port)<<" desport: "<<ntohs(tcppacket->tcpheader.des_port)<<endl;
    cout<<"seq: "<<ntohl(tcppacket->tcpheader.seq)<<" ack: "<<ntohl(tcppacket->tcpheader.ack)<<endl;
}

void rawsocsniffer::ParseUDPPacket()
{
    udp_packet_t *udppacket=(udp_packet_t *)packet;
    cout<<setw(20)<<"MAC address: from ";
    print_hw_addr(udppacket->etherheader.src_hw_addr);
    cout<<"to ";
    print_hw_addr(udppacket->etherheader.des_hw_addr);
    cout<<endl<<setw(20)<<"IP address: from ";
    print_ip_addr(udppacket->ipheader.src_ip);
    cout<<"to ";
    print_ip_addr(udppacket->ipheader.des_ip);
    cout<<endl;
    cout<<setw(10)<<"srcport: "<<ntohs(udppacket->udpheader.src_port)<<" desport: "<<ntohs(udppacket->udpheader.des_port)\
	<<" length:"<<ntohs(udppacket->udpheader.len)<<endl;
}

void rawsocsniffer::print_hw_addr(const unsigned char *ptr)
{
    cout<<"hw addr:";
    for (size_t i = 0; i < 6; i++)
        printf("%02x ",ntohs(ptr[i])) ;
}

void rawsocsniffer::print_ip_addr(const unsigned int ip)
{
    cout<<"ip addr:"<<endl;
    
    uint32_t masks[4]={0xFF,0xFF00,0x00FF0000,0xFF000000};
    for (size_t i = 0; i < 4; i++)
        printf("%03d.",ntohs(ip & masks[i])>>(8*i));
    

}

void rawsocsniffer::ParseICMPPacket()
{
    icmp_packet_t *icmppacket=(icmp_packet_t *)packet;
    cout<<setw(20)<<"MAC address: from ";
    print_hw_addr(icmppacket->etherheader.src_hw_addr);
    cout<<"to ";
    print_hw_addr(icmppacket->etherheader.des_hw_addr);
    cout<<endl<<setw(20)<<"IP address: from ";
    print_ip_addr(icmppacket->ipheader.src_ip);
    cout<<"to ";
    print_ip_addr(icmppacket->ipheader.des_ip);
    cout<<endl;
    cout<<setw(10)<<"type: "<<ntohs(icmppacket->icmpheader.type)<<" code: "<<ntohs(icmppacket->icmpheader.code)\
	<<" checksum: "<<ntohs(icmppacket->icmpheader.checksum)<<" id: "<<ntohs(icmppacket->icmpheader.id)<<endl\
    <<" seq: "<<ntohs(icmppacket->icmpheader.seq)<<endl;    
}

void rawsocsniffer::ParseRARPPacket()
{

}

void rawsocsniffer::ParseARPPacket()
{
    arp_packet_t *arppacket=(arp_packet_t *)packet;
    cout<<setw(20)<<"MAC address: from ";
    print_hw_addr(arppacket->etherheader.src_hw_addr);
    cout<<"to ";
    print_hw_addr(arppacket->etherheader.des_hw_addr);
    cout<<endl<<setw(20)<<"hw type:"<<ntohs(arppacket->arpheader.hw_type)<<endl\
    <<" prot type:"<<ntohs(arppacket->arpheader.prot_type)<<endl\
    <<" hw addr len:"<<ntohs(arppacket->arpheader.hw_addr_len)<<endl\
    <<" prot addr len:"<<ntohs(arppacket->arpheader.prot_addr_len)<<endl\
    <<" flag:"<<ntohs(arppacket->arpheader.flag);

    cout<<endl<<setw(20)<<"IP address: from ";
    print_ip_addr(arppacket->arpheader.send_prot_addr);
    cout<<"to ";
    print_ip_addr(arppacket->arpheader.des_prot_addr);
     


}

int main()
{
    rawsocsniffer sniffer(htons(ETH_P_ALL)); 
    filter myf = {0,0,0xFFFFFFFF};
    sniffer.setfilter(myf);
    sniffer.sniffer();
}